#include "systick.h"

static __IO uint32_t TimingDelay;

/* 系统接管中断函数时，使用另外的方法来实现延时函数 */
#ifndef SYS_SUPPORT_OS

void Systick_Init() {
    if (SysTick_Config(SystemCoreClock / 1000000U)) {
        /* Capture error */
        while (1);
    }
}

/**
 * @brief  Inserts a delay time.
 * @param  nTime: specifies the delay time length, in microseconds.
 * @retval None
 */
void Delay_us(__IO uint32_t nTime) {
    TimingDelay = nTime;

    while (TimingDelay != 0);
}

/**
 * @brief  Inserts a delay time.
 * @param  nTime: specifies the delay time length, in milliseconds.
 * @retval None
 */
void Delay_ms(__IO uint32_t nTime) {
    TimingDelay = nTime * 1000;

    while (TimingDelay != 0);
}

/**
 * @brief  Decrements the TimingDelay variable.
 * @param  None
 * @retval None
 */
void TimingDelay_Decrement(void) {
    if (TimingDelay != 0x00) {
        --TimingDelay;
    }
}

#else

/* 通过计算tick的新旧差值来实现微秒延时函数 */
void Delay_us(__IO uint32_t nTime) {
    uint32_t ticks;
    uint32_t told, tnow, reload, tcnt = 0;
    reload = SysTick->LOAD;
    ticks  = nTime * (SystemCoreClock / 1000000);
    told   = SysTick->VAL;

    while (1) {
        tnow = SysTick->VAL;
        if (tnow != told) {
            // 计数器还未递减到0
            if (tnow < told) tcnt += (told - tnow);
            // 计数器已经递减到0重装载过了
            else
                tcnt += (reload - tnow + told);

            // 每轮更新旧的told值
            told = tnow;

            // 可能会有小误差
            if (tcnt >= ticks) break;
        }
    }
}

void Delay_ms(__IO uint32_t nTime) {
    uint32_t i;
    for (i = 0; i < nTime; ++i) {
        Delay_us(1000);
    }
}

#endif
